package com.esd.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.esd.common.pojo.R;
import com.esd.device.entity.Device;
import com.esd.device.entity.DeviceChannel;
import com.esd.device.entity.EsdLog;
import com.esd.device.entity.Line;
import com.esd.device.entity.vo.*;
import com.esd.device.mapper.DeviceChannelMapper;
import com.esd.device.mapper.DeviceMapper;
import com.esd.device.mapper.EsdLogMapper;
import com.esd.device.mapper.LineMapper;
import com.esd.device.service.LineService;
import com.esd.device.task.DeviceConstants;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class LineServiceImpl extends ServiceImpl<LineMapper, Line> implements LineService {
    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public R deleteById(Long lineId) {
        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getLineId, lineId);
        Device device = deviceMapper.selectOne(queryWrapper, false);
        if (device != null) {
            return R.error("该产线下存在关联的终端！不能删除。");
        }
        baseMapper.deleteById(lineId);
        return R.ok("删除产线成功！！");
    }

    @Override
    public R addLine(Line line) {
        LambdaQueryWrapper<Line> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Line::getLineName, line.getLineName());
        Line line1 = baseMapper.selectOne(queryWrapper);
        if (line1 != null) {
            return R.error("生产线已存在，请查询编辑！！");
        }
        baseMapper.insert(line);
        return R.ok("添加生产线成功！！");
    }

    @Override
    public R updateLine(Line line) {
        LambdaQueryWrapper<Line> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Line::getLineName, line.getLineName());
        Line line1 = baseMapper.selectOne(queryWrapper);
        if (line1 != null && !Objects.equals(line1.getLineId(), line.getLineId())) {
            return R.error("生产线已存在，请查询编辑！！");
        }
        baseMapper.updateById(line);
        return R.ok("编辑生产线成功！！");
    }

    @Override
    public R saveModule(Map<String, String> params) {
        String lineName = params.get("lineName");
        LambdaQueryWrapper<Line> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Line::getLineName, lineName);
        Line line = baseMapper.selectOne(queryWrapper, false);
        line.setModulesHtml(params.get("dom"));
        baseMapper.updateById(line);
        return R.ok("模型保存成功！！");
    }

    @Override
    public R getModule(String lineName) {
        LambdaQueryWrapper<Line> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Line::getLineName, lineName);
        Line line = baseMapper.selectOne(queryWrapper);
        String html = line.getModulesHtml();
        if (html != null && !html.isEmpty()) {
            Document doc = Jsoup.parse(html);
            Elements elements = doc.select("img");
            List<Map<String, String>> imgList = new ArrayList<>();
            for (Element element : elements) {
                Map<String, String> map = new HashMap<>();
                map.put("id", element.attr("id"));
                map.put("src", element.attr("src"));
                map.put("style", element.attr("style"));
                imgList.add(map);
            }
            return R.ok(imgList);
        }
        return R.error();
    }

    @Value("${module.images.jsonPath}")
    private String jsonPath;

    @Override
    public R getModuleImages() {
        ObjectMapper mapper = new ObjectMapper();
        try {
            List<ImageVo> list = mapper.readValue(
                    new File(jsonPath),
                    mapper.getTypeFactory().constructCollectionType(List.class, ImageVo.class));
            if (list != null) {
                list.forEach(a -> a.setPath("/images/module/" + a.getPath()));
                List<List<ImageVo>> result = new ArrayList<>();
                int i = 0;
                while (i < list.size()) {
                    List<ImageVo> list1;
                    if (i + 6 < list.size()) {
                        list1 = list.subList(i, i + 6);
                    } else {
                        list1 = list.subList(i, list.size());
                    }
                    result.add(list1);
                    i = i + 6;
                }
                return R.ok(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.ok(new ArrayList<>());
    }

    @Autowired
    private DeviceChannelMapper deviceChannelMapper;

    @Transactional
    @Override
    public R getPositions(String lineName) {
        LambdaQueryWrapper<Line> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Line::getLineName, lineName);
        Line line = baseMapper.selectOne(queryWrapper);
        // 生成初始化的 SettingPositionVo 列表
        List<SettingPositionVo> positionVos = generatePositionVos(line.getLineId());
        String html = line.getPositionsHtml();
        if (html != null && !html.trim().isEmpty()) {
            // 补充 初始化的 SettingPositionVo 中未设置的 style 属性
            Map<String, String> styleMap = getPosition(html);
            positionVos.forEach(settingPositionVo -> {
                if (styleMap.containsKey(settingPositionVo.getId())) {
                    settingPositionVo.setStyle(styleMap.get(settingPositionVo.getId()));
                }
            });
        }
        return R.ok(positionVos);
    }

    private Map<String , String> getPosition(String html){
        Document doc = Jsoup.parse(html);
        Elements elements = doc.select("span[class=position]");
        Map<String , String> styleMap = new HashMap<>();
        for (Element element : elements) {
            styleMap.put(element.attr("id") , element.attr("style")) ;
        }
        return styleMap ;
    }

    // 生成初始化的 SettingPositionVo 列表
    @Override
    public List<SettingPositionVo> generatePositionVos(Long lineId) {
        List<SettingPositionVo> positionVos = new ArrayList<>();
        LambdaQueryWrapper<Device> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Device::getLineId, lineId);
        queryWrapper1.eq(Device::getViewEnabled , true );
//        queryWrapper1.notLike(Device::getDeviceType, "%离子风扇") ;
        List<Device> devices = deviceMapper.selectList(queryWrapper1);
        devices.forEach(device -> {
            LambdaQueryWrapper<DeviceChannel> deviceChannelLambdaQueryWrapper = new LambdaQueryWrapper<>();
            deviceChannelLambdaQueryWrapper.eq(DeviceChannel::getDeviceId, device.getDeviceId());
            List<DeviceChannel> deviceChannels = deviceChannelMapper.selectList(deviceChannelLambdaQueryWrapper);
            for (int i = 0; i < deviceChannels.size(); i++) {
                SettingPositionVo settingPositionVo = new SettingPositionVo();
                settingPositionVo.setId(device.getStationId() + "_" + (i + 1));
                settingPositionVo.setPositionName(device.getPosition() + "_" + (i + 1));
                settingPositionVo.setStyle("");
                settingPositionVo.setEnabled(deviceChannels.get(i).getEnabled());
                settingPositionVo.setChannelType(deviceChannels.get(i).getChannelType());
                positionVos.add(settingPositionVo);
            }
        });
        return positionVos ;
    }

    @Override
    public R getCurrentStatus(String lineName) {
        List<SettingPositionVo> settingPositionVos = (List<SettingPositionVo>) getPositions(lineName).getData();
        List<DashBoardDeviceVo> dashBoardDeviceVos = new ArrayList<>();
        settingPositionVos.forEach(settingPositionVo -> {
            DashBoardDeviceVo dashBoardDeviceVo = new DashBoardDeviceVo();
            BeanUtils.copyProperties(settingPositionVo , dashBoardDeviceVo);
            dashBoardDeviceVos.add(dashBoardDeviceVo) ;
        });
        Map<String , Object> deviceMap = new HashMap<>();
        deviceMap.put("channelName", "设备接地");
        deviceMap.put("icon", "/backend/images/SVG/EM0.svg");
        deviceMap.put("normal", 0);
        deviceMap.put("error", 0);
        deviceMap.put("standBy", 0);
        deviceMap.put("miss", 0);
        deviceMap.put("total", 0) ;
        Map<String , Object> tdMap = new HashMap<>();
        tdMap.put("channelName", "台垫接地");
        tdMap.put("icon", "/backend/images/SVG/RR0.svg");
        tdMap.put("normal", 0);
        tdMap.put("error", 0);
        tdMap.put("standBy", 0);
        tdMap.put("miss", 0);
        tdMap.put("total", 0) ;
        Map<String , Object> manMap = new HashMap<>();
        manMap.put("channelName", "ESD手环");
        manMap.put("icon", "/backend/images/SVG/WH0.svg");
        manMap.put("normal", 0);
        manMap.put("error", 0);
        manMap.put("miss", 0);
        manMap.put("standBy", 0);
        manMap.put("total", 0) ;
        Map<String , Object> fanMap = new HashMap<>();
        fanMap.put("channelName", "离子风扇");
        fanMap.put("icon", "/backend/images/SVG/EN0.svg");
        fanMap.put("normal", 0);
        fanMap.put("error", 0);
        fanMap.put("standBy", 0);
        fanMap.put("miss", 0);
        fanMap.put("total", 0) ;
        Map<String , Object> temMap = new HashMap<>();
        temMap.put("channelName", "温度计");
        temMap.put("icon", "/backend/images/SVG/TE1.svg");
        temMap.put("normal", 0);
        temMap.put("error", 0);
        temMap.put("standBy", 0);
        temMap.put("miss", 0);
        temMap.put("total", 0) ;
        Map<String , Object> humMap = new HashMap<>();
        humMap.put("channelName", "湿度计");
        humMap.put("icon", "/backend/images/SVG/HU0.svg");
        humMap.put("normal", 0);
        humMap.put("error", 0);
        humMap.put("standBy", 0);
        humMap.put("miss", 0);
        humMap.put("total", 0) ;
        Map<String , Object> chenMap = new HashMap<>();
        chenMap.put("channelName", "尘埃粒子");
        chenMap.put("icon", "/backend/images/SVG/CL1.svg");
        chenMap.put("normal", 0);
        chenMap.put("error", 0);
        chenMap.put("standBy", 0);
        chenMap.put("miss", 0);
        chenMap.put("total", 0) ;
        if (!dashBoardDeviceVos.isEmpty()){
            dashBoardDeviceVos.forEach(dashBoardDeviceVo -> {
                if(DeviceConstants.ChannelStatusMap.containsKey(dashBoardDeviceVo.getId())) {
                    PositionStoreVo positionStoreVo = DeviceConstants.ChannelStatusMap.get(dashBoardDeviceVo.getId());
                    dashBoardDeviceVo.setStatus(positionStoreVo.getStatus());
                    dashBoardDeviceVo.setDetail(positionStoreVo.getDetail());
                }else {
                    dashBoardDeviceVo.setStatus("失联");
                    dashBoardDeviceVo.setDetail("失联");
                }
                if (dashBoardDeviceVo.getEnabled()){
                    if (dashBoardDeviceVo.getChannelType().equals("设备接地")){
                        if (dashBoardDeviceVo.getStatus().equals("正常")){
                            deviceMap.put("normal", (Integer)deviceMap.get("normal") + 1);
                        }else if(dashBoardDeviceVo.getStatus().equals("异常")){
                            deviceMap.put("error", (Integer)deviceMap.get("error") + 1);
                        }else{
                            deviceMap.put("miss", (Integer)deviceMap.get("miss") + 1);
                        }
                        deviceMap.put("total", (Integer)deviceMap.get("total") + 1);
                    }
                    if (dashBoardDeviceVo.getChannelType().equals("台垫接地")){
                        if (dashBoardDeviceVo.getStatus().equals("正常")){
                            tdMap.put("normal", (Integer)tdMap.get("normal") + 1);
                        }else if(dashBoardDeviceVo.getStatus().equals("异常")){
                            tdMap.put("error", (Integer)tdMap.get("error") + 1);
                        }else{
                            tdMap.put("miss", (Integer)tdMap.get("miss") + 1);
                        }
                        tdMap.put("total", (Integer)tdMap.get("total") + 1);
                    }
                    if (dashBoardDeviceVo.getChannelType().equals("ESD手环")){
                        switch (dashBoardDeviceVo.getStatus()) {
                            case "正常":
                                manMap.put("normal", (Integer) manMap.get("normal") + 1);
                                break;
                            case "异常":
                                manMap.put("error", (Integer) manMap.get("error") + 1);
                                break;
                            case "待机":
                                manMap.put("standBy", (Integer) manMap.get("standBy") + 1);
                                break;
                            default:
                                manMap.put("miss", (Integer) manMap.get("miss") + 1);
                                break;
                        }
                        manMap.put("total", (Integer)manMap.get("total") + 1);
                    }
                    if (dashBoardDeviceVo.getChannelType().equals("离子风扇")){
                        switch (dashBoardDeviceVo.getStatus()) {
                            case "正常":
                                fanMap.put("normal", (Integer) fanMap.get("normal") + 1);
                                break;
                            case "异常":
                                fanMap.put("error", (Integer) fanMap.get("error") + 1);
                                break;
                            case "待机":
                                fanMap.put("standBy", (Integer) fanMap.get("standBy") + 1);
                                break;
                            default:
                                fanMap.put("miss", (Integer) fanMap.get("miss") + 1);
                                break;
                        }
                        fanMap.put("total", (Integer)fanMap.get("total") + 1);
                    }
                    if (dashBoardDeviceVo.getChannelType().equals("温度计")){
                        switch (dashBoardDeviceVo.getStatus()) {
                            case "正常":
                                temMap.put("normal", (Integer) temMap.get("normal") + 1);
                                break;
                            case "异常":
                                temMap.put("error", (Integer) temMap.get("error") + 1);
                                break;
                            case "待机":
                                temMap.put("standBy", (Integer) temMap.get("standBy") + 1);
                                break;
                            default:
                                temMap.put("miss", (Integer) temMap.get("miss") + 1);
                                break;
                        }
                        temMap.put("total", (Integer)temMap.get("total") + 1);
                    }

                    if (dashBoardDeviceVo.getChannelType().equals("湿度计")){
                        switch (dashBoardDeviceVo.getStatus()) {
                            case "正常":
                                humMap.put("normal", (Integer) humMap.get("normal") + 1);
                                break;
                            case "异常":
                                humMap.put("error", (Integer) humMap.get("error") + 1);
                                break;
                            case "待机":
                                humMap.put("standBy", (Integer) humMap.get("standBy") + 1);
                                break;
                            default:
                                humMap.put("miss", (Integer) humMap.get("miss") + 1);
                                break;
                        }
                        humMap.put("total", (Integer)humMap.get("total") + 1);
                    }

                    if (dashBoardDeviceVo.getChannelType().equals("尘埃粒子")){
                        switch (dashBoardDeviceVo.getStatus()) {
                            case "正常":
                                chenMap.put("normal", (Integer) chenMap.get("normal") + 1);
                                break;
                            case "异常":
                                chenMap.put("error", (Integer) chenMap.get("error") + 1);
                                break;
                            case "待机":
                                chenMap.put("standBy", (Integer) chenMap.get("standBy") + 1);
                                break;
                            default:
                                chenMap.put("miss", (Integer) chenMap.get("miss") + 1);
                                break;
                        }
                        chenMap.put("total", (Integer)chenMap.get("total") + 1);
                    }
                }
            });
        }
        Map<String , Object> totalMap = new HashMap<>();
        totalMap.put("channelName" , "总计") ;
        totalMap.put("normal", (Integer)deviceMap.get("normal")
                + (Integer) tdMap.get("normal")
                + (Integer)manMap.get("normal")
                + (Integer)fanMap.get("normal")
                + (Integer)temMap.get("normal")
                + (Integer)humMap.get("normal")
                + (Integer)chenMap.get("normal"));
        totalMap.put("error", (Integer)deviceMap.get("error")
                + (Integer) tdMap.get("error")
                + (Integer)manMap.get("error")
                + (Integer)fanMap.get("error")
                + (Integer)temMap.get("error")
                + (Integer)humMap.get("error")
                + (Integer)chenMap.get("error"));
        totalMap.put("miss", (Integer)deviceMap.get("miss")
                + (Integer) tdMap.get("miss")
                + (Integer)manMap.get("miss")
                + (Integer)fanMap.get("miss")
                + (Integer)temMap.get("miss")
                + (Integer)humMap.get("miss")
                + (Integer)chenMap.get("miss"));
        totalMap.put("standBy", (Integer)deviceMap.get("standBy")
                + (Integer) tdMap.get("standBy")
                + (Integer)manMap.get("standBy")
                + (Integer)fanMap.get("standBy"));
        totalMap.put("total", (Integer)deviceMap.get("total")
                + (Integer) tdMap.get("total")
                + (Integer)manMap.get("total")
                + (Integer)fanMap.get("total")
                + (Integer)temMap.get("total")
                + (Integer)humMap.get("total")
                + (Integer)chenMap.get("total"));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("totalMap", totalMap);
        resultMap.put("positionList", dashBoardDeviceVos);
        List<Map<String , Object>> list =  new ArrayList<>();
        if((int)deviceMap.get("total") != 0){
            list.add(deviceMap) ;
        }
        if((int)tdMap.get("total") != 0){
            list.add(tdMap) ;
        }
        if((int)manMap.get("total") != 0){
            list.add(manMap) ;
        }
        if((int)fanMap.get("total") != 0){
            list.add(fanMap) ;
        }
        if((int)temMap.get("total") != 0){
            list.add(temMap) ;
        }
        if((int)humMap.get("total") != 0){
            list.add(humMap) ;
        }
        if((int)chenMap.get("total") != 0){
            list.add(chenMap) ;
        }
        list.add(totalMap);
        resultMap.put("analysisList", list);
        return R.ok(resultMap);
    }

    @Override
    public R getLineCount() {
        Long count = baseMapper.selectCount(null);
        return R.ok(count);
    }

    @Value("${dashboard.page_size}")
    private int page_size ;

    @Autowired
    private LineMapper lineMapper ;

    @Override
    public List<List<LineData>> getLineDataList() {
        List<LineData> lineDataList = new ArrayList<>();
        List<Line> lines = lineMapper.selectAllHasDevice();
        lines.forEach(line -> {
            LineData lineData = new LineData();
            lineData.setLineName(line.getLineName());
            List<ShowDeviceVo> showDeviceVoList =  deviceMapper.getShowDeviceVoList(line.getLineId());
            showDeviceVoList.forEach(showDeviceVo -> {
                // 查询通道数据
                List<DeviceChannelVo> deviceChannelVos = deviceChannelMapper.getListByDeviceId(showDeviceVo.getDeviceId());
                List<HashMap<String ,String>> channels = new ArrayList<>();
                for (int i = 0; i < deviceChannelVos.size(); i++) {
                    if (deviceChannelVos.get(i).getEnabled()) {
                        HashMap<String, String> channel = new HashMap<>();
                        channel.put("channelType", deviceChannelVos.get(i).getChannelTypeName());
                        channel.put("channelNum" , "通道" + (i + 1)) ;
                        channel.put("position", deviceChannelVos.get(i).getPosition()) ;
                        // 查询通道数据详情
                        PositionStoreVo positionStoreVo = DeviceConstants.ChannelStatusMap.get(showDeviceVo.getId() + "_"+ (i + 1));
                        if (positionStoreVo != null) {
                            channel.put("channelStatus", positionStoreVo.getStatus());
                            channel.put("channelDetail", positionStoreVo.getDetail());
                        }else {
                            channel.put("channelStatus", "失联");
                            channel.put("channelDetail", "失联");
                        }
                        if (showDeviceVo.getDeviceTypeName().equals("离子风扇")){
                            if (positionStoreVo != null ) {
                                channel.put("balancePower", positionStoreVo.getBalancePower());
                                channel.put("fdzPower", positionStoreVo.getFdzPower());
                            }else {
                                channel.put("balancePower", "0V");
                                channel.put("fdzPower", "0V");
                            }
                        }
                        channels.add(channel);
                    }
                }
                showDeviceVo.setChannels(channels);
            });
            // 数据分行
            List<List<ShowDeviceVo>> result = new ArrayList<>();
            int i = 0;
            while (i < showDeviceVoList.size()) {
                List<ShowDeviceVo> list1;
                if (i + 12 < showDeviceVoList.size()) {
                    list1 = showDeviceVoList.subList(i, i + 12);
                } else {
                    list1 = showDeviceVoList.subList(i, showDeviceVoList.size());
                }
                result.add(list1);
                i = i + 12;
            }
            lineData.setRowList(result);
            lineDataList.add(lineData);
        });
        // 数据分页
        List<List<LineData>> pageResult = new ArrayList<>();
        int i = 0;
        while (i < lineDataList.size()) {
            List<LineData> list1;
            if (i + page_size < lineDataList.size()) {
                list1 = lineDataList.subList(i, i + page_size);
            } else {
                list1 = lineDataList.subList(i, lineDataList.size());
            }
            pageResult.add(list1);
            i = i + page_size;
        }
        return pageResult;
    }

    @Autowired
    private EsdLogMapper esdLogMapper ;

    @Transactional
    @Override
    public R setViewOn(Long lineId, String value) {
        int i = lineMapper.setViewOn(lineId, value);
        if (i > 0 && value.equals("0")){
            Line line = baseMapper.selectById(lineId);
            LambdaQueryWrapper<EsdLog>  queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(EsdLog::getLine , line.getLineName());
            EsdLog esdLog = new EsdLog() ;
            esdLog.setEndTime(LocalDateTime.now());
            esdLogMapper.update(esdLog, queryWrapper) ;
        }
        return R.ok();
    }

    @Override
    public R savePositions(Map<String, String> params) {
        String lineName = params.get("lineName");
        LambdaQueryWrapper<Line> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Line::getLineName, lineName);
        Line line = baseMapper.selectOne(queryWrapper, false);
        line.setPositionsHtml(params.get("dom"));
        baseMapper.updateById(line);
        return R.ok("站点位置保存成功！！");
    }
}
